/*
 * @(#)ToolBarButtonFactory.java  1.2  2006-07-16
 *
 * Copyright (c) 1996-2006 by the original authors of JHotDraw
 * and all its contributors ("JHotDraw.org")
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * JHotDraw.org ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance
 * with the terms of the license agreement you entered into with
 * JHotDraw.org.
 */

package umage.core;

import org.jhotdraw.util.*;
import org.jhotdraw.draw.action.*;
import java.util.Comparator;
import java.util.List;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.*;
import java.lang.reflect.Constructor;
import java.util.*;
import javax.swing.*;
import org.jhotdraw.app.action.*;
import org.jhotdraw.draw.*;

import umage.action.ActionInfo;
import umage.action.DefaultAction;
import umage.figures.FigureInfo;

/**
 * ToolBarButtonFactory.
 *
 * @author Werner Randelshofer
 * @version 1.2 2006-07-16 Split some methods up for better reuse. 
 * <br>1.1 2006-03-27 Font exclusion list updated.
 * <br>1.0 13. Februar 2006 Created.
 */
public class UMageMenuManager {
    
    protected static class PriorityMenu {
    	public JMenu menu;
    	public int priority;
    	
    	public PriorityMenu(JMenu menu, int priority) {
    		this.menu = menu;
    		this.priority = priority;
    	}
    }
    
    protected UMageApplication app;
    protected HashMap<String, PriorityMenu> menus;
    protected HashMap<Class<? extends DefaultAction>, JMenuItem> items;
    
    public UMageMenuManager(UMageApplication app) {
    	menus = new HashMap<String, PriorityMenu>();
    	items = new HashMap<Class<? extends DefaultAction>, JMenuItem>();
    	this.app = app;
    }
    
    /**
     * Method addSelectionToolTo must have been invoked prior to this on the
     * JToolBar.
     *
     */
    public void addAction(Class<? extends DefaultAction> action) {
    	
    	ActionInfo actionInfo = action.getAnnotation(ActionInfo.class);
    	String name;
    	Icon icon;
    	String menu;
    	int menuPriority;
    	if (actionInfo != null) {
    		name = actionInfo.name();
    		if (actionInfo.icon().length() > 0) icon = ImageUtil.getImageIcon(actionInfo.icon(), "/umage/action/images/");
    		else icon = null;
    		menu = actionInfo.menu();
    		menuPriority = actionInfo.menuPriority();
    	} else return; // Just ignore actions without action info
    	
    	DefaultAction actionInstance = createAction(action);
    	if (actionInstance == null) return;
    	
        JMenuItem t = getItem(action);
        t.setAction(actionInstance);
        t.setText(name);
        t.setIcon(icon);
        t.setFocusable(false);
        getMenu(menu, menuPriority).add(t);
    }
    
    protected DefaultAction createAction(Class<? extends DefaultAction> action) {
    	
    	// Construct the action
    	DefaultAction a = null;
    	try {
			a = action.newInstance();
			a.setApplication(app);
			return a;
		} catch (InstantiationException e) {
			System.err.println("Proper action constructor is not public or does not exist");
			return null;
		} catch (IllegalAccessException e) {
			System.err.println("Proper action constructor is not public or does not exist");
			return null;
		} catch (Exception e) {
			System.err.println("Initial Action Construction Failed:");
			e.printStackTrace();
			return null;
		}
	}

	protected JMenu getMenu(String name, int priority) {
    	PriorityMenu pMenu = menus.get(name);
    	if (pMenu == null) {
    		pMenu = new PriorityMenu(new JMenu(), priority);
    		pMenu.menu.setName(name);
    		pMenu.menu.setText(name);
    		menus.put(name, pMenu);
    	} else if (pMenu.priority < priority) {
    		pMenu.priority = priority;
    	}
    	return pMenu.menu;
    }
    
    protected JMenuItem getItem(Class<? extends DefaultAction> action) {
    	JMenuItem item = items.get(action);
    	if (item == null) {
    		item = new JMenuItem();
    		items.put(action, item);
    	}
    	return item;
    }
    
    public List<JMenu> getMenuList() {
    	Collection<PriorityMenu> vals = menus.values();
    	PriorityMenu menus[] = new PriorityMenu[vals.size()];
    	vals.toArray(menus);
    	Arrays.sort(menus, new Comparator<PriorityMenu>() {
			@Override
			public int compare(PriorityMenu o1, PriorityMenu o2) {
				return o1.priority - o2.priority;
			}
    	});
    	ArrayList<JMenu> list = new ArrayList<JMenu>(menus.length);
    	for (PriorityMenu pMenu : menus) {
    		list.add(pMenu.menu);
    	}
    	return list;
    }
    
    public void updateVisibleMenus(List<Class<? extends DefaultAction>> actions) {
    	
    	// Remove visiblity on all menu items
    	for (JMenuItem item : items.values()) {
    		item.setVisible(false);
    	}
    	
    	// Add visiblity to items and menus as specified
    	for (Class<? extends DefaultAction> action : actions) {
    		JMenuItem item = items.get(action);
    		if (item != null) {
    			item.setVisible(true);
    		}
    	}
    	
    	// Remove visiblity on all menus except those with visible children
    	menuLoop:
    	for (PriorityMenu pMenu : menus.values()) {
    		for (Component c : pMenu.menu.getMenuComponents()) {
    			if (c instanceof JMenuItem && ((JMenuItem)c).isVisible()) {
    				pMenu.menu.setVisible(true);
    				continue menuLoop;
    			}
    		}
    		pMenu.menu.setVisible(false);
    	}
    }
    
}
